// $Id: ComputeAgent.java 1932 2013-01-29 14:40:05Z phil $


package sma.jade;

import jade.core.*;
import jade.core.behaviours.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import jade.lang.acl.*;

/**
 * This agent can compute the integral of a given real function
 *   on a given interval with a given precision (step granularity).
 * <br>
 * It uses a Function object for the sake of genericity.
 * @author laroque@u-cergy.fr
 * @version $Rev: 1932 $
 */
public class ComputeAgent extends Agent {

  /** the function to evaluate */
  protected Function f;

  /**
   * The agent first register itself ("compute" service), then
   *   cyclicly listen for computation requests. <br>
   * Such request contains a Function object that embed all
   *   computation parameters.
   */
  protected void setup() {


    // register "compute" capabilities
    ServiceDescription sd  = new ServiceDescription();
    sd.setType( "compute" );
    sd.setName( "a compute agent" );
    register( sd );
    //f = new Function(0,0,0);
    f = null;

    // cyclicly listen for queries for computation
    addBehaviour(new CyclicBehaviour(this) {
        public void action() {
          MessageTemplate mt =
            MessageTemplate.MatchPerformative( ACLMessage.REQUEST );
          ACLMessage msg= receive(mt);
          if (msg!=null) {
            // got a request: extract computation parameters
            try {
              f = (Function) msg.getContentObject();
            } catch (Exception e) {}
            ACLMessage reply = msg.createReply();

            // actual computation
            double d = f.eval();

            // build and send reply to request sender
            reply.setContent("" + d);
            System.err.println(myAgent.getLocalName()
                               + " replies " + d);
            send(reply);
          }
          block();
        }
      });
  }

  /** called by doDelete, standard way to de-register from the DF*/
  protected void takeDown() {
    try { DFService.deregister(this); }
    catch (Exception e) {}
  }

  /**
   * Useful wrapper for registering services : hides the usage of the
   * DFD
   */
  void register( ServiceDescription sd) {
    DFAgentDescription dfd = new DFAgentDescription();
    dfd.setName(getAID());
    dfd.addServices(sd);

    try {
      DFService.register(this, dfd );
    }
    catch (FIPAException fe) { fe.printStackTrace(); }
  }
}
